package com.webinsky.web.resource;

import java.time.Duration;
import java.util.List;

import javax.annotation.PostConstruct;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.server.WebSession;

import com.webinsky.common.utils.EmailUtils;
import com.webinsky.common.utils.EmailUtils.EmailContent;
import com.webinsky.domain.user.Account;
import com.webinsky.domain.user.AccountFilter;
import com.webinsky.domain.user.Role;
import com.webinsky.service.user.AuthorizationManagement;
import com.webinsky.service.user.UserManagement;
import com.webinsky.web.data.AccountFilterForm;
import com.webinsky.web.data.LoginCodeForm;
import com.webinsky.web.data.LoginForm;
import com.webinsky.web.data.RegisterForm;
import com.webinsky.web.data.Response;
import com.webinsky.web.data.UidIntForm;
import com.webinsky.web.utils.AsyncMessage;
import com.webinsky.web.utils.CodeUtils;
import com.webinsky.web.utils.EmailMessage;
import com.webinsky.web.utils.Message;
import com.webinsky.web.utils.WebSessionUtils;

import reactor.core.publisher.Mono;


@Component
public class UserResource {
	
	private static Logger logger = LoggerFactory.getLogger(UserResource.class);
	
	@Autowired
	private AuthorizationManagement authorizationManagement;
	@Autowired
	private UserManagement userManagement;
	private AsyncMessage asyncMessage = AsyncMessage.create();
	private String sendAddress = "noreply@softinsky.com"; 
	@Value("${email.recieve.address}")
	private String recAddresses;
	@Value("${email.smtp.host}")
	private String smtpHost;
	@Value("${email.smtp.port}")
	private int smtpPort;
	@Value("${email.smtp.username}")
	private String smtpUserName;
	@Value("${email.smtp.password}")
	private String smtpPassword;
	
	private String[] recAddress;

	private String adminEmailTemplate = "验证码:%s";
	@PostConstruct
	public void init(){
		asyncMessage.start();
		if ( recAddresses != null ){
			recAddress = recAddresses.split(",");
		}
	}
	
	private String genCode(WebSession session){
		String randomCode = CodeUtils.genCode(5);
		WebSessionUtils.setVerfycode(session, randomCode);
		logger.info("{}genCode = " + randomCode);
		return String.format(adminEmailTemplate, randomCode);
	}
	
	/**
	 * 用户登陆
	 * @param request
	 * @return
	 */
	public Mono<ServerResponse> login(ServerRequest request){
		return request.session().zipWith(request.bodyToMono(LoginForm.class)).flatMap(data -> {
			LoginForm loginForm = data.getT2();
			WebSession session = data.getT1();
			session.setMaxIdleTime(Duration.ofDays(1));
			if ( !StringUtils.isEmpty(loginForm.name) && !StringUtils.isEmpty(loginForm.password)) {
				Account account = authorizationManagement.login(loginForm.name, loginForm.password);
				if ( account != null ){
					account.setPassword(null);
					Role role = Role.parse(account.getRole());
					if ( role != null ){
						if ( role == Role.SuperAdmin ){
							// send email
							EmailContent emailContent = new EmailContent();
							emailContent.smtpServer = new EmailUtils.EmailSmtpServre();
							emailContent.smtpServer.smtpServer = smtpHost;
							emailContent.smtpServer.smtpPort = smtpPort;
							emailContent.smtpServer.smtpUserName = smtpUserName;
							emailContent.smtpServer.smtpPassword = smtpPassword;
							emailContent.smtpServer.smtpIsSSL = true;
							emailContent.from = new EmailUtils.EmailFrom();
							emailContent.from.formName = sendAddress;
							emailContent.from.fromEMail = sendAddress;
							emailContent.sender = new EmailUtils.EmailSent();
							emailContent.sender.subject = "WEBINSKY登录验证码";
							emailContent.sender.recievers = recAddress;
							emailContent.sender.body = genCode(session);
							Message message = new EmailMessage(emailContent);
							asyncMessage.addMessage(message);
						}
					}
					WebSessionUtils.putAccount(session, account);
					WebSessionUtils.setAdminIsLogin(session, Boolean.FALSE);
					WebSessionUtils.setCodeExpireTime(session);
					return ServerResponse.ok().syncBody(Response.create(account, Response.STATUS_OK, ""));
				}
				return ServerResponse.ok().syncBody(Response.create("", Response.STATUS_NOTFOUND_ERROR, "用户名和密码不匹配, 请确认!"));
			}
			return ServerResponse.ok().syncBody(Response.create("", Response.STATUS_WRONGARUGS_ERROR, "请正确输入用户名和密码!"));
		});
	}
	
	/**
	 * @param request
	 * @return
	 */
	public Mono<ServerResponse> adminLoginVerify(ServerRequest request){
		return request.session().zipWith(request.bodyToMono(LoginCodeForm.class)).flatMap( data -> {
			WebSession session = data.getT1();
			LoginCodeForm form = data.getT2();
			String verfyCode = WebSessionUtils.getVerfycode(session);
			if ( verfyCode != null ){
				if ( verfyCode.equals(form.code) ){
					WebSessionUtils.setAdminIsLogin(session, Boolean.TRUE);
					return ServerResponse.ok().syncBody(Response.create("", Response.STATUS_OK, ""));
				}
				return ServerResponse.ok().syncBody(Response.create("", Response.STATUS_WRONGARUGS_ERROR, "验证码不正确, 请确认!"));
			}
			return ServerResponse.ok().syncBody(Response.create("", Response.STATUS_NOTFOUND_ERROR, "没有找到"));
		});
	}
	
	/**
	 * 用户登出
	 * @param request
	 * @return
	 */
	public Mono<ServerResponse> logout(ServerRequest request){
		return request.session().flatMap(session -> {
			session.invalidate().subscribe();
			return ServerResponse.ok().syncBody(Response.create("", Response.STATUS_OK, ""));
		});
	}
	/**
	 * check login
	 * @param request
	 * @return
	 */
	public Mono<ServerResponse> checkLogin(ServerRequest request){
		return request.session().flatMap(session -> {
			if ( WebSessionUtils.getAccount(session) != null ){
				int roleId = WebSessionUtils.getAccount(session).getRole();
				Role role = Role.parse(roleId);
				if ( role == Role.SuperAdmin ){
					if ( WebSessionUtils.adminIsLogin(session) ) {
						return ServerResponse.ok().syncBody(Response.create("", Response.STATUS_OK, ""));
					}
					return ServerResponse.ok().syncBody(Response.create("", Response.STATUS_NOTFOUND_ERROR, "用户没有登陆"));
				}
				return ServerResponse.ok().syncBody(Response.create("", Response.STATUS_OK, ""));
			}
			return ServerResponse.ok().syncBody(Response.create("", Response.STATUS_NOTFOUND_ERROR, "用户没有登陆"));
		});
	}

	public Mono<ServerResponse> keepsession(ServerRequest request){
		return ServerResponse.ok().syncBody(Response.create("", Response.STATUS_OK, ""));
	}

	public Mono<ServerResponse> createAccount(ServerRequest request){
		return request.bodyToMono(RegisterForm.class).flatMap(form -> {
			Account account = new Account();
			account.setLoginName(form.loginName);
			account.setUserName(form.userName);
			account.setPassword(form.password);
			account.setRole(Integer.valueOf(form.role));
			account.setSiteId(form.siteId);
			// authorizationManagement.register(account);
			account = userManagement.createAccount(account);
			return ServerResponse.ok().syncBody(Response.create(account.getUid(), Response.STATUS_OK, ""));
		});
	}

	public Mono<ServerResponse> updateAccount(ServerRequest request){
		return request.bodyToMono(RegisterForm.class).flatMap(form -> {
			Account account = new Account();
			account.setUid(form.uid);
			account.setLoginName(form.loginName);
			account.setUserName(form.userName);
			account.setPassword(form.password);
			account.setRole(Integer.valueOf(form.role));
			account.setSiteId(form.siteId);
			// authorizationManagement.register(account);
			userManagement.updateAccount(account);
			return ServerResponse.ok().syncBody(Response.create(account.getUid(), Response.STATUS_OK, ""));
		});
	}

	public Mono<ServerResponse> deleteAccount(ServerRequest request){
		return request.bodyToMono(UidIntForm.class).flatMap(form -> {
			userManagement.deleteAccount(form.uid);
			return ServerResponse.ok().syncBody(Response.create("", Response.STATUS_OK, ""));
		});
	}

	public Mono<ServerResponse> filterAccount(ServerRequest request){
		return request.bodyToMono(AccountFilterForm.class).flatMap(form -> {
			AccountFilter filter = new AccountFilter();
			filter.setName(form.name);
			List<Account> list = userManagement.filterAccount(filter);
			return ServerResponse.ok().syncBody(Response.create(list, Response.STATUS_OK, ""));
		});
	}

}
